#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cexapi
import datetime
import time
import re
import math
import logging

logging.basicConfig(format='%(asctime)s; %(message)s', filename='trade.log',level=logging.DEBUG)

credentialFile = open('credentials.txt', 'r+')
for line in credentialFile:
        resultLine = re.split(';', line)  
        if resultLine[0]=='hannesh':
            apiUser=resultLine[0]
            apiCred1=resultLine[1]
            apiCred2=resultLine[2] 
demo = cexapi.api(apiUser, apiCred1, apiCred2)


terminateSellPrice = 0.414141

pause=2 #seconds
initialPause=100 #seconds
old_fortune=0
fortuneBTC=0
old_fortuneBTC=0
fortuneGHS=0

ghs_smallBoundaries=0.0001
ghs_pkgsize=0.01
ghs_LargePkgsize=0.2

diffSize4Largerghspkg=300
lowerLimitDiffSize=20

satoshi=0.00000001    
medium_price=0.01
fortuneBTC=1
fortuneGHS=1
sigRun=1
        
criticalGHSThreshold=0.29
criticalBTCThreshold=0.2  

def iBetrag(real,imaginaer):
    sqr=(real*real)+(imaginaer*imaginaer)
    return math.sqrt(sqr)
def ghs_sizePkgCalc(diff):
    ghs_size_ret=ghs_smallBoundaries
    if diff<7000:
        ghs_size_ret=7000*ghs_pkgsize/diff
    
    if ghs_size_ret>ghs_LargePkgsize:
        ghs_size_ret=ghs_LargePkgsize#-((0.1*diff/250)+0.1)
    
    if ghs_size_ret<0:
        ghs_size=ghs_LargePkgsize
          
    return ghs_size_ret
def ghs_totCritical():
    retVal=1
    try:
        retVal=ghs_tot/fortuneGHS<criticalGHSThreshold
    except:
        retVal=0
    return retVal    
def btc_totCritical():
    retVal=1
    try: 
        retVal=btc_tot/fortuneBTC<criticalBTCThreshold
    except: 
        retVal=0
    return retVal
def terminateOrder(sortedCurrOrders):
    retVal=1    
    highOrder=sortedCurrOrders[0]
    if float(highOrder['price'])==terminateSellPrice:
        print "Terminate Order",highOrder
        demo.cancel_order(highOrder['id'])
        retVal=0
    return retVal
def removeOuterSellBuy(sortedCurrOrders):
    try:
        sellRemoved=0
        buyRemoved=0
        print "remove outer SELL BUY" 
        #print sortedCurrOrders
        outer_sell_order=0
        outer_buy_order=0
        for order in sortedCurrOrders:            
            if order['type']=='sell':            
                if float(order['amount'])>ghs_smallBoundaries and not outer_sell_order:
                    outer_sell_order=order
                elif order['type']=='buy':            
                    if float(order['amount'])>ghs_smallBoundaries:
                        outer_buy_order=order
            if outer_sell_order:
                time.sleep(1)
                print "remove outer Sell",outer_sell_order    
                demo.cancel_order(outer_sell_order['id'])
                sellRemoved=1
                
            if outer_buy_order:
                time.sleep(1)
                print "remove outer_buy",outer_buy_order
                demo.cancel_order(outer_buy_order['id'])
                buyRemoved=1  
    
    except:
       print "Unexpected Error in removeOuterSellBuy"
       raise
    return sellRemoved and buyRemoved 

def getFromBal(GHSBTC,avl_orders):

    retVal=0
    try:
        retVal=float(bal[GHSBTC][avl_orders])
    except:
        retVal=0
    return retVal

def strRound(number,anzStellen):
    return str(round(number,anzStellen))

      
        
while sigRun:
    try:
        bal = demo.balance()
        ghs_avl=getFromBal('GHS','available')
        ghs_orders=getFromBal('GHS','orders')
        ghs_tot = ghs_avl+ghs_orders
    
        btc_avl=getFromBal('BTC','available')
        btc_orders=getFromBal('BTC','orders')
        btc_tot = btc_avl+btc_orders

        currOrders = demo.current_orders()

        sortedCurrOrders = sorted(currOrders, key=lambda order: order['price'], reverse=True)
        
        sigRun=terminateOrder(sortedCurrOrders)
        
        if ghs_avl<ghs_LargePkgsize or btc_avl<medium_price*ghs_LargePkgsize:                       
            sellAndBuyRemoved=removeOuterSellBuy(sortedCurrOrders)
             
    
        sell_min=-1
        buy_max=-1
        weighSumSell=0
        weighSumBuy=0
        
        for order in sortedCurrOrders:
            if order['type']=='sell':
                sell_min=order['price']
                sell_min_amount=order['amount']
                weighSumSell=weighSumSell+(float(order['pending'])*float(order['price']))
            else:
                weighSumBuy=weighSumBuy+(float(order['pending'])*float(order['price']))
                if  buy_max<0:
                    buy_max=order['price']
                    buy_max_amount=order['amount']
                    
        sellBuyDiff=(float(sell_min)-float(buy_max))*100000000
        if sellBuyDiff>10000:
            initialPause=1
        else: 
            initialPause=100
             
           
        upper=float(sell_min)
        lower=float(buy_max)
        price_point=(upper+lower)/2        
        diff=(upper-lower)/8
        diffSemi=(upper-lower)/32        
        sell_price=round(price_point+(3*diff),8)
        buy_price=round(price_point-(3*diff),8)
            
        medium_price=(sell_price+buy_price)/2 
        ticker = demo.ticker()   
        lastPrice=float(ticker['last'])
        
        ticker_sell_price=round(lastPrice+(3*diff),8)
        ticker_buy_price=round(lastPrice-(3*diff),8)
           
        print "__________________________________"
            
        print "sellBuyDiff=",round(sellBuyDiff,2)
        print " ToSell =",round(weighSumSell,4),"  ToBuy = ",round(weighSumBuy,4)
        print "ghs_avl =",round(ghs_avl,4), "ghs_tot =",round(ghs_tot,4)
        print "btc_avl =",round(btc_avl,4), "btc_tot = ",round(btc_tot,4)        
        if sellBuyDiff>lowerLimitDiffSize:
            useGhsPkgSize=ghs_sizePkgCalc(sellBuyDiff)
            useGhsPkgSizeSell=useGhsPkgSize
            useGhsPkgSizeBuy=useGhsPkgSize
            print "pkgSize =",round(useGhsPkgSize,3)
            
            if (ghs_avl>useGhsPkgSize and btc_avl>buy_price*useGhsPkgSize):
                if sell_price-buy_price>=satoshi:   
                    if ghs_totCritical() or btc_totCritical(): 
                        print "\nTicker last price=",lastPrice
                        orderbook = demo.order_book()
                        askPrice=orderbook['asks'][0][0]
                        askAmount=orderbook['asks'][0][1]
                        bidPrice=orderbook['bids'][0][0]
                        bidAmount=orderbook['bids'][0][1]

                        if ghs_tot/fortuneGHS<criticalGHSThreshold:
                          print "ghs_tot/fortuneGHS=",ghs_tot/fortuneGHS                          
                          bietPreis=askPrice+satoshi
                          print "buy GHS 0.01 for ", bietPreis
                          demo.place_order('buy',min(askAmount,0.1),bietPreis)
                        else:                          
                          print "btc_tot/fortuneBTC=",btc_tot/fortuneBTC
                          verkaufBietPreis=bidPrice-satoshi
                          print "sell GHS 0.02 for",verkaufBietPreis
                          demo.place_order('buy',min(bidAmount,0.1),verkaufBietPreis)                          
                    else:
                        demo.place_order('sell',useGhsPkgSizeSell,ticker_sell_price)
                        print "place sell, price=",ticker_sell_price, "pkgSize=",round(useGhsPkgSizeSell,4)
                        #demo.place_order('sell',useGhsPkgSizeSell,sell_price)
                        #print "place sell, price=",sell_price, "pkgSize=",round(useGhsPkgSizeSell,4)
                        demo.place_order('buy',useGhsPkgSizeBuy,ticker_buy_price)
                        print " place buy, price=",ticker_buy_price, "pkgSize=",round(useGhsPkgSizeBuy,4) 
                        #demo.place_order('buy',useGhsPkgSizeBuy,buy_price)
                        #print " place buy, price=",buy_price, "pkgSize=",round(useGhsPkgSizeBuy,4)                    
                else:
                    print "sell and buy too close"
            else:
                print ghs_avl,">!",useGhsPkgSize, "and", btc_avl, ">!",buy_price*useGhsPkgSize
        else:
            print "sellBuyDiff-Limit erreicht"
                
        old_fortuneBTC=fortuneBTC
        fortuneBTC=round(((sell_price+buy_price)*ghs_tot/2)+btc_tot,8)
        fortuneGHS=round(ghs_tot+(btc_tot/medium_price),8)
        print "\nmedPrice   =",medium_price        
        print "  ticker   =",lastPrice    
        print "fortuneBTC =",fortuneBTC,""
        #print "fortBTCTxC =",round(0.0114*fortuneBTC/lastPrice,8)       
        print "fortuneGHS =",fortuneGHS
        #print "fortGHSTxC =",round(0.0114*fortuneGHS/lastPrice,8)
        referenceIBetrag=39.865293548
        iBetragVal=iBetrag(100*fortuneBTC,fortuneGHS)
        print "iBetrag    =",iBetragVal
        print "dIBetrag   =",round(iBetragVal-referenceIBetrag,4)
        
        logToken=";ticker="+strRound(lastPrice,8)+"\
        ;fortuneBTC="+strRound(fortuneBTC,8)+"\
        ;medPrice="+strRound(medium_price,8)+"\
        ;fortuneGHS="+strRound(fortuneGHS,8)+"\
        ;iBetrag="+strRound(iBetragVal,8)+"\
        ;dIBetrag="+strRound(iBetragVal-referenceIBetrag,4)+"\
        ;;"
        
        logging.info(logToken) 
        print "----------------------------------"
    except:
        print "Unexpected Error"
        #raise
    time.sleep(min(pause,initialPause))








